package com.wmh.baseservice.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.wmh.baseservice.admin.cache.permission.RoleRepository;
import com.wmh.baseservice.admin.entity.AdRole;
import com.wmh.baseservice.admin.mapper.AdRoleMapper;
import com.wmh.baseservice.admin.pojo.vo.role.AddRoleReqVO;
import com.wmh.baseservice.admin.pojo.vo.role.BaseFields;
import com.wmh.baseservice.admin.pojo.vo.role.UpdateRoleReqVO;
import com.wmh.baseservice.admin.service.AdRoleMenuService;
import com.wmh.baseservice.admin.service.AdRoleService;
import com.wmh.baseservice.admin.service.AdUserRoleService;
import com.wmh.baseservice.admin.tools.enums.AdRoleEnum;
import com.wmh.baseservice.admin.tools.enums.AdRoleStatus;
import com.wmh.baseservice.common.ex.ServiceException;
import com.wmh.baseservice.common.mybatisplus.methods.CommonServiceImpl;
import com.wmh.baseservice.common.mybatisplus.structure.LambdaQueryWrapperX;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author mmx generator
 * @since 2021-02-03
 */
@Service
@Slf4j
public class AdRoleServiceImpl extends CommonServiceImpl<AdRoleMapper, AdRole> implements AdRoleService {

    @Resource
    @Lazy
    private AdRoleMenuService adRoleMenuService;

    @Resource
    @Lazy
    private AdUserRoleService adUserRoleService;

    @Resource
    private HttpServletRequest request;

    @Resource
    private RoleRepository roleRepository;

    @PostConstruct
    public void init() {
        log.info("开始预热角色缓存");
        roleRepository.clear();
        List<AdRole> roles = baseMapper.selectList(null);
        roleRepository.setRole(roles);
        log.info("缓存角色数量 : [{}]", roles.size());
    }

    @Override
    public void addV2(AddRoleReqVO reqVO) {
        checkNameUniqueness(null, reqVO);
        AdRole entity = BaseFields.buildEntity(null, reqVO).setStatus(1);
        baseMapper.insert(entity);
        roleRepository.setRole(entity);
    }

    @Override
    public void updateV2(UpdateRoleReqVO reqVO) {
        checkRoleExists(reqVO.getId());
        checkNameUniqueness(reqVO.getId(), reqVO);
        AdRole entity = BaseFields.buildEntity(reqVO.getId(), reqVO);
        baseMapper.updateById(entity);
        roleRepository.setRole(entity);
    }

    private void checkNameUniqueness(Long id, BaseFields baseFields) {
        AdRole entity = baseMapper.selectOne(new LambdaQueryWrapperX<AdRole>()
                .neIfPresent(AdRole::getId, id)
                .eq(AdRole::getRoleName, baseFields.getName()));
        if (entity != null) {
            throw new ServiceException("存在相同的角色名称");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Long> ids) {
        if (ids.contains(AdRoleEnum.SUPER_ADMIN.getId())) {
            throw new ServiceException("无法操作超级管理员");
        }
        if (!removeByIds(ids)) {
            throw new ServiceException("删除失败 请重试或联系管理员");
        }
        roleRepository.delRole(ids);
        // 角色与菜单映射的连带删除
        ids.forEach(item -> adRoleMenuService.delete(item));
        // 管理员与角色的连带删除
        adUserRoleService.deleteRole(ids.toArray(new Long[0]));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(Long roleId, Integer status) {
        if (AdRoleEnum.SUPER_ADMIN.getId().equals(roleId)) {
            throw new ServiceException("无法操作超级管理员");
        }
        if (!status.equals(AdRoleStatus.NORMAL.getValue()) && !status.equals(AdRoleStatus.FREEZE.getValue())) {
            throw new ServiceException("系统字典没有该状态编号 : " + status);
        }
        AdRole adRole = getById(roleId);
        if (adRole == null) {
            throw new ServiceException("该角色数据在系统中不存在 : " + roleId);
        }
        if (!updateById(adRole.setStatus(status))) {
            throw new ServiceException("修改角色状态失败 请重试或关系管理员");
        }
        roleRepository.setRole(adRole);
    }

    @Override
    public List<AdRole> getAdRolesByCache(Long adId, AdRoleStatus status) {
        List<AdRole> r = roleRepository.getList(adUserRoleService.getRoleIdsByCache(adId));
        if (isHasSupperAdmin(CollUtil.map(r, AdRole::getId, true))) {
            r = roleRepository.getAll();
        }
        if (status != null) {
            r = r.stream().filter(f -> status.getValue().equals(f.getStatus())).collect(Collectors.toList());
        }
        return r;
    }


    @Override
    public boolean isHasSupperAdmin(Long adId) {
        return getAdRolesByCache(adId, AdRoleStatus.NORMAL).stream().anyMatch(role -> Objects.equals(role.getId(), AdRoleEnum.SUPER_ADMIN.getId()));
    }

    @Override
    public boolean isHasSupperAdmin(List<Long> roleIds) {
        return roleIds.contains(AdRoleEnum.SUPER_ADMIN.getId());
    }

    @Override
    public void checkRoleExists(Long roleId) {
        AdRole entity = baseMapper.selectById(roleId);
        if (entity == null) {
            throw new ServiceException("该角色不存在");
        }
    }

}
